/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.compomics.fastaconverter.triplet;

import com.compomics.fastaconverter.sequence.SubSequence;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Kenneth
 */
public class TripletConverter {

    private static File input;
    private static File output;
    private static String startLetter = "M";
    private static boolean includeUnlikely = false;
    private static int minLength = 15;
    private static RandomAccessFile file;
    private static RandomAccessFile outputFile;
    private static HashSet<String> headers = new HashSet<String>();

    ;

    public TripletConverter(File input, File output) {
        this.input = input;
        this.output = output;
    }

    public void convertFrame() throws FileNotFoundException {
        setupStreams();
        StringBuilder sequence = null;
        String strLine;;
        try {
            sequence = new StringBuilder();
            String header = null;
            while (file.getFilePointer() < file.length()) {
                strLine = file.readLine();
                if (strLine.startsWith(">")) {
                    if (header != null) {
                        convertEntry(sequence.toString(), header + "_[5-3]");
                        convertEntry(sequence.reverse().toString(), header + "_[3-5]");
                        //empty the sequence
                        sequence = sequence.delete(0, sequence.length());
                    }
                    //start a new sequence
                    header = strLine.substring(1);
                } else {
                    sequence.append(strLine);
                }
            }
            if (!sequence.toString().isEmpty()) {
                //also convert the last one !
                convertEntry(sequence.toString(), header + "[5-3]");
                convertEntry(sequence.reverse().toString(), header + "[3-5]");
            }

        } catch (Exception e) {//Catch exception if any
            e.printStackTrace();
        } finally {
        }
    }

    private static List<SubSequence> getSubSequences(StringBuilder sequence) {
        List<SubSequence> subSequences = new ArrayList<SubSequence>();
        String regex = startLetter + "[^\\*]*\\*?";
        Pattern p = Pattern.compile(regex);
        Matcher match = p.matcher(sequence.toString());
        while (match.find()) {
            subSequences.add(new SubSequence(sequence.substring(match.start(), match.end()), match.start(), match.end()));
        }
        return subSequences;
    }

    private static void convertEntry(String sequence, String header) throws IOException {
        //Split the strig in triplets ! 
        for (int frame = 0; frame < 3; frame++) {
            //standard format = >generic_contig-535081|AC:123132|Hypothetical protein
            String subheader = (">generic|" + header + "_FRAME[" + (frame + 1) + "]");
            StringBuilder totalTranslatedSequence = new StringBuilder();
            if (sequence.length() > 3) {
                String framedSequence = sequence.substring(frame, sequence.length() - sequence.length() % 3);
                for (int i = 0; i <= framedSequence.length() - 3; i = i + 3) {
                    totalTranslatedSequence.append(TripletFactory.getTripletSingleLetter(framedSequence.substring(i, i + 3)));
                }
                splitSubSequences(totalTranslatedSequence, subheader);
            }
        }
    }

    private static void splitSubSequences(StringBuilder sequence, String subHeader) throws IOException {

        List<SubSequence> subSequences = getSubSequences(sequence);
        for (SubSequence aSubSequence : subSequences) {
            StringBuilder printHeader = new StringBuilder().append(subHeader).append("_subsequence[").append(aSubSequence.getStartIndex()).append("-").append(aSubSequence.getEndIndex()).append("]|").append(" TRANSLATION");

            if ((aSubSequence.getEndIndex() - aSubSequence.getStartIndex()) < minLength) {
                printHeader.append("_UNLIKELY");
            }

            if (aSubSequence.getSequence().length() >= minLength || includeUnlikely) {
                if (!headers.contains(printHeader.toString())) {
                    if (aSubSequence.getSequence().indexOf("*") == -1) {
                        printHeader.append("_endless");
                    } else {
                        aSubSequence.setSequence(aSubSequence.getSequence().replace("*", "X"));
                    }
                    printHeader.append(System.lineSeparator());
                    outputFile.writeBytes(printHeader.toString());
                    outputFile.writeBytes(aSubSequence.getSequence() + System.lineSeparator());
                    headers.add(printHeader.toString());
                }
            }
        }
        headers.clear();
    }

    private static void setupStreams() throws FileNotFoundException {
        file = new RandomAccessFile(input.getAbsolutePath(), "rw");
        outputFile = new RandomAccessFile(output.getAbsolutePath(), "rw");
    }

    public void setStart(String startLetter) {
        this.startLetter = startLetter;
    }

    public void setIncludeUnlikely(boolean includeUnlikely) {
        this.includeUnlikely = includeUnlikely;
    }

    public void setUnlikelyTreshold(int unlikelyTreshold) {
        this.minLength = unlikelyTreshold;
    }
}
